home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ADA Programming Guide
/
ADA Programming Guide.iso
/
ada_pcdp
/
adas
/
expr.pas
< prev
next >
Wrap
Pascal/Delphi Source File
|
1996-01-30
|
8KB
|
273 lines
unit expr;
{ Compile expressions including
assignment statements and procedure calls }
interface
uses global, util;
procedure selector(level: integer; var v: item);
procedure expression(level: integer; var x: item);
procedure call(level: integer; i: integer);
procedure assignment(level,i: integer; lv, ad:integer);
implementation
procedure selector(level: integer; var v: item);
var x: item;
a,j: integer;
begin
if sy <> lparent then error(ertyp);
insymbol;
expression(level, x);
if v.typ <> arrays then error(ertyp);
a := v.ref;
if atab[a].inxtyp <> x.typ then error(ertyp);
emit1(21,a);
v.typ := atab[a].eltyp;
v.ref := 0;
if sy = rparent then insymbol else error(erpun)
end;
procedure call(level: integer; i: integer);
var x: item;
lastp, cp: integer;
procedure valueparameter;
begin
expression(level, x);
if x.typ <> tab[cp].typ then error(ertyp);
if x.typ = arrays then error(ertyp); { arrays not allowed }
if x.ref <> tab[cp].ref then error(ertyp);
end;
procedure variableparameter;
var k: integer;
begin
if sy <> ident then error(erid);
k := loc(level, id);
insymbol;
if k = 0 then error(ernf);
with tab[k] do
begin
if obj <> variable then error(erpar);
x.typ := typ;
x.ref := ref;
if normal then emit2(0, lev, adr) else
emit2(1, lev, adr);
if sy = lparent then
selector(level, x);
if (x.typ <> tab[cp].typ) or (x.ref <> tab[cp].ref) then
error(ertyp)
end
end;
begin (* call *)
emit1(18,i); (* markstack *)
lastp := btab[tab[i].ref].lastpar;
cp := i;
if sy = lparent then
begin
repeat
insymbol;
if cp >= lastp then error(erpar);
cp := cp + 1;
if tab[cp].normal then valueparameter else variableparameter
until sy <> comma;
if sy = rparent then insymbol else error(erpun)
end;
if cp < lastp then error(erpar); (* too few actual parms *)
emit1(19, btab[tab[i].ref].psize-1);
if tab[i].lev < level then emit2(3, tab[i].lev, level)
end;
function resulttype(a,b: types): types;
begin
if (a>ints) or (b>ints) then error(ertyp);
if (a=notyp) or (b=notyp) then resulttype := notyp
else resulttype := ints
end;
procedure expression(level: integer; var x: item);
var y: item;
op: symbol;
procedure simpleexpression(var x: item);
var y: item;
op: symbol;
procedure term(var x: item);
var y: item;
op: symbol;
ts: typset;
procedure factor(var x: item);
var i,f: integer;
begin
x.typ := notyp;
x.ref := 0;
while sy in facbegsys do
begin
if sy = ident then
begin
i := loc(level, id);
if i = 0 then error(ernf);
insymbol;
with tab[i] do
case obj of
konstant:
begin
x.typ := typ;
x.ref := 0;
emit1(24, adr)
end;
variable:
begin
x.typ := typ;
x.ref := ref;
if sy = lparent then
begin
if normal then f := 0 else f := 1;
emit2(f, lev, adr);
selector(level, x);
if x.typ in stantyps then emit(34) else error(ertyp)
end
else begin
if not(x.typ in stantyps) then error(ertyp);
if normal then f := 1 else f := 2;
emit2(f, lev, adr)
end
end;
type1, prozedure, task: error(ertyp);
end (* case *)
end
else if sy in [charcon, intcon] then
begin
if sy = charcon then x.typ := chars else x.typ := ints;
emit1(24, inum);
x.ref := 0;
insymbol
end
else if sy = lparent then
begin
insymbol;
expression(level, x);
if sy = rparent then insymbol else error(erpun)
end
else if sy = notsy then
begin
insymbol;
factor(x);
if x.typ = bools then emit(35)
else if x.typ <> notyp then error(ertyp)
end;
end (* while *)
end;
begin(* term *)
factor(x);
while sy in [times, idiv, imod, andsy] do
begin
op := sy;
insymbol;
factor(y);
if op = times then
begin
x.typ := resulttype(x.typ, y.typ);
if x.typ = ints then emit(57)
end
else if op = andsy then
begin
if (x.typ = bools) and (y.typ = bools) then emit(56)
else begin
if (x.typ <> notyp) and (y.typ <> notyp) then error(ertyp);
x.typ := notyp
end
end
else begin (* op in [idiv, imod *)
if (x.typ = ints) and (y.typ = ints) then
if op = idiv then emit(58) else emit(59)
else begin
if (x.typ <> notyp) and (y.typ <> notyp) then error(ertyp);
x.typ := notyp
end
end
end
end;
begin (* simpleexpression *)
if sy in [plus, minus] then
begin
op := sy;
insymbol;
term(x);
if x.typ > ints then error(ertyp)
else if op = minus then emit(36)
end
else term(x);
while sy in [plus, minus, orsy] do
begin
op := sy;
insymbol;
term(y);
if op = orsy then
begin
if (x.typ = bools) and (y.typ = bools) then emit(51)
else begin
if (x.typ <> notyp) and (y.typ <> notyp) then error(ertyp);
x.typ := notyp
end
end
else begin
x.typ := resulttype(x.typ, y.typ);
if x.typ = ints then
if op = plus then emit(52) else emit(53)
end
end
end;
begin (* expression *)
simpleexpression(x);
if sy in [eql, neq, gtr, lss, leq, geq] then
begin
op := sy;
insymbol;
simpleexpression(y);
if (x.typ in [notyp, ints, bools, chars]) and (x.typ = y.typ) then
case op of
eql: emit(45);
neq: emit(46);
lss: emit(47);
leq: emit(48);
gtr: emit(49);
geq: emit(50)
end
else error(ertyp);
x.typ := bools
end
end;
procedure assignment(level, i: integer; lv, ad: integer);
var x, y: item;
f: integer;
watch: boolean;
{ Standard variables (integer, character, boolean)
will be "watched": store will print value }
begin
watch := true;
x.typ := tab[i].typ;
x.ref := tab[i].ref;
if tab[i].normal then f := 0
else begin watch := false; f := 1 end;
emit2(f, lv, ad);
if sy = lparent then
begin
watch := false; selector(level, x) end;
if sy = becomes then insymbol else error(erpun);
expression(level, y);
if (x.typ = y.typ) and (x.typ in stantyps)
then if watch then emit1(38, i) { save tab index for watch }
else emit1(38, 0) { 0 = no watch }
else error(ertyp)
end;
end.